<?php

/**
 * 订单资费计算
 */

namespace App\Services;

use App\Models\DrivingTariff;
use App\Models\OrderDistance;
use App\Models\Orders;
use App\Models\Tariff;
use App\Models\User;
use Ixudra\Curl\Facades\Curl;

class DriversPostage
{
    /**
     * @param $data
     * @return mixed
     * @throws \App\Exceptions\BobException
     * 路线规划
     */
    public function getDriveRoute($data)
    {
        $data['key'] = env('AMAP_WEB_KEY');
        $url = 'restapi.amap.com/v3/direction/driving';
        $response = Curl::to($url)->withData($data)->get();
        $response = json_decode($response, true);
        if ($response['status'] != 1)
            return_bob($response['info']);

        return $response['route'];
    }

    /**
     * 司机所得费用结算
     */
    public function DriverOrderSettlement(int $order_id)
    {
        $info = Orders::query()->with('order_distance')->where('id', $order_id)->first();
        return $this->getPredictByLoLas($info->order_distance->reality_start_coord, $info->order_distance->reality_end_coord, $info->order_distance->reality_start_time, $info->order_distance->reality_end_time, $info->service_type_id, $type = '2', $info->company_id, $order_id);
    }

    /**
     * 代驾司机所得费用结算
     */
    public function drvingDriverOrderSettlement(int $order_id)
    {
        $info = Orders::query()->with('order_distance')->where('id', $order_id)->where('type', '1')->first();
        return $this->drivingGetPredictByLoLas($info->order_distance->reality_start_coord, $info->order_distance->reality_end_coord, $info->order_distance->reality_start_time, $info->order_distance->reality_end_time, $info->service_type_id, $type = '2', $info->company_id, $order_id,$info);
    }

    /**
     * 超时等待费用
     */
    public function waiting_timeout(int $order_id, $data, $start_minute): float
    {
        $info = Orders::query()->with('order_distance')->select(['id', 'company_id', 'service_type_id', 'arrive_time'])->where('id', $order_id)->first();
        $minute = floor((strtotime($info->order_distance->reality_start_time) - $info->arrive_time) % 86400 / 60); //计算出分钟数
        if (!$minute) return 0;
        if (!$data) return 0;

        $rest = self::waiting_timeouts($data);
        if ($minute > $start_minute) {
            return number_format(floor($minute - $start_minute) * $rest, 2);
        }
        return 0;
    }

    /**
     * 超时等待费用
     * @param $rules
     * @return array
     */
    protected function waiting_timeouts(array $rules)
    {
        $minute_cost_arr = [];
        foreach ($rules as $k => $rule) {
//            if($rule['start_time'] == '普通时段'){
//              // continue;
//            }
            return $minute_cost_arr[$k]['price'] = $rule['price'];
        }

    }

    /**
     * 司机代驾订单费用计算
     *
     */

    public function EstimatedCost(int $order_id)
    {
        $info = Orders::query()->with('order_distance')->where('id', $order_id)->first();
        $default_driver_company_id = \App\Models\ServiceCity::query()->where('city_id', $info->city_id)->first('default_driver_company_id');
        $infos = self::dvingPredictByLoLass($info->order_distance->book_start_coord, $info->order_distance->book_end_coord, $types = '2', $default_driver_company_id->default_driver_company_id);
        $infos['order_id'] = $info->id;
        $infos['book_start'] = $info->order_distance->book_start; //预约起点
        $infos['book_end'] = $info->order_distance->book_end; //预约终点
        $infos['book_start_coord'] = $info->order_distance->book_start_coord; //预约起点经纬度
        $infos['book_end_coord'] = $info->order_distance->book_end_coord;  //预约终点经纬度
        $infos['reality_start'] = $info->order_distance->reality_start; //实际起点位置
        $infos['end_time'] = $info->end_time; //实际起点位置
        $infos['type'] = $info->type; //实际起点位置
        $infos['user'] = User::query()->where('id', $info->user_id)->first(['phone', 'name', 'nick_name', 'avatar']); //用户信息
        foreach ($infos['steps'] as $step) {
            $aa[] = explode(';', $step['polyline']);
            $res_arr = [];
            array_walk_recursive($aa, function ($k) use (&$res_arr) {
                $res_arr[] = $k;
            });
        }
        OrderDistance::query()->where('order_id', $order_id)->update(['tail_info' => json_encode($res_arr)]); //更新轨迹信息
        unset($infos['basics_cost'], $infos['basics_cost'], $infos['total_mileage_cost'], $infos['total_duration_cost'], $infos['total_long_distance_cost'], $infos['mileage'], $infos['duration'], $infos['long_distance'], $infos['steps']);
        return $infos;
    }

    /**
     * @param int $order_id
     * @return array
     */
    public function EstimatedCostInt(int $order_id)
    {
        $info = Orders::query()->with('order_distance')->where('id', $order_id)->first();
        $default_driver_company_id = \App\Models\ServiceCity::query()->where('city_id', $info->city_id)->first('default_driver_company_id');
        $infos = self::dvingPredictByLoLass($info->order_distance->book_start_coord, $info->order_distance->book_end_coord, $types = '2', $default_driver_company_id->default_driver_company_id);
        $infos['order_id'] = $info->id;
        $infos['book_start'] = $info->order_distance->book_start; //预约起点
        $infos['book_end'] = $info->order_distance->book_end; //预约终点
        $infos['book_start_coord'] = $info->order_distance->book_start_coord; //预约起点经纬度
        $infos['book_end_coord'] = $info->order_distance->book_end_coord;  //预约终点经纬度
        $infos['reality_start'] = $info->order_distance->reality_start; //实际起点位置
        $infos['end_time'] = $info->end_time; //实际起点位置
        $infos['type'] = $info->type; //实际起点位置
        $infos['user'] = User::query()->where('id', $info->user_id)->first(['phone', 'name', 'nick_name', 'avatar']); //用户信息
        foreach ($infos['steps'] as $step) {
            $aa[] = explode(';', $step['polyline']);
            $res_arr = [];
            array_walk_recursive($aa, function ($k) use (&$res_arr) {
                $res_arr[] = $k;
            });
        }
        OrderDistance::query()->where('order_id', $order_id)->update(['tail_info' => json_encode($res_arr)]); //更新轨迹信息
        unset($infos['basics_cost'], $infos['basics_cost'], $infos['total_mileage_cost'], $infos['total_duration_cost'], $infos['total_long_distance_cost'], $infos['mileage'], $infos['duration'], $infos['long_distance'], $infos['steps']);
        return $infos;
    }

    /**
     * 司机预计所得费用计算
     */
    public function DriversEstimatedCost(int $order_id)
    {
        $info = Orders::query()->with('order_distance')->where('id', $order_id)->first();

        return self::getPredictByLoLass($info->order_distance->book_start_coord, $info->order_distance->book_end_coord, $info->service_type_id, $type = '2', $info->company_id, $info->arrive_time);

    }

    /**
     * 司机距离乘客距离计算
     */
    public function DriversEstimatedCostssss($origin, $destination)
    {
        $route = $this->getDriveRoute(['origin' => $origin, 'destination' => $destination]);
        $path = $route['paths'][0];
        $total_distance = $path['distance']; //总距离 m
        $total_distance_km = floor($total_distance / 1000 * 100) / 100; //总距离 km
        $total_time = $path['duration'] / 60; //总耗时 分钟
        $total_time_int_m = $total_time / 60 == 0 ? (int)$total_time : ((int)$total_time + 1); //总耗时 整分
        $data = ['total_distance_km' => $total_distance_km, 'total_time_int_m' => floor($total_time)];
        return $data;
    }

    /**
     * 司机预计所得费用计算
     */
    public function DriversEstimatedCosts(int $order_id, $type)
    {

        $info = Orders::query()->with('order_distance')->where('id', $order_id)->first();
        $default_driver_company_id = \App\Models\ServiceCity::query()->where('city_id', $info->city_id)->first('default_driver_company_id');
        $infos = self::getPredictByLoLass($info->order_distance->book_start_coord, $info->order_distance->book_end_coord, $type, $types = '2', $default_driver_company_id->default_driver_company_id);
        $infos['order_id'] = $info->id;
        $infos['book_start'] = $info->order_distance->book_start; //预约起点
        $infos['book_end'] = $info->order_distance->book_end; //预约终点
        $infos['book_start_coord'] = $info->order_distance->book_start_coord; //预约起点经纬度
        $infos['book_end_coord'] = $info->order_distance->book_end_coord;  //预约终点经纬度
        $infos['reality_start'] = $info->order_distance->reality_start; //实际起点位置
        $infos['type'] = $info->type; //实际起点位置
        $infos['end_time'] = $info->end_time; //结算时间
        $infos['user'] = User::query()->where('id', $info->user_id)->first(['phone', 'name', 'nick_name', 'avatar']); //用户信息
        foreach ($infos['steps'] as $step) {
            $aa[] = explode(';', $step['polyline']);
            $res_arr = [];
            array_walk_recursive($aa, function ($k) use (&$res_arr) {
                $res_arr[] = $k;
            });
        }
        OrderDistance::query()->where('order_id', $order_id)->update(['tail_info' => json_encode($res_arr)]); //更新轨迹信息
        unset($infos['basics_cost'], $infos['basics_cost'], $infos['total_mileage_cost'], $infos['total_duration_cost'], $infos['total_long_distance_cost'], $infos['mileage'], $infos['duration'], $infos['long_distance'], $infos['steps']);
        return $infos;
    }

    /**
     * @param $origin
     * @param $destination
     * @param $service_type_id 业务类型ID
     * @param $type 类型：1-乘客，2-司机
     * @param $company_id 公司ID
     * @return array
     * @throws \App\Exceptions\BobException
     */
    private function getPredictByLoLass($origin, $destination, $service_type_id, $type, $company_id)
    {

        $route = $this->getDriveRoute(['origin' => $origin, 'destination' => $destination]);

        $path = $route['paths'][0];
        $total_distance = $path['distance']; //总距离 m
        $total_distance_km = floor($total_distance / 1000 * 100) / 100; //总距离 km
        $total_time = $path['duration']; //总耗时
        $total_time_int_m = $total_time % 60 == 0 ? (int)$total_time : ((int)$total_time + 60); //总耗时 整分
        //获取资费信息
        $where = [];
        if ($company_id > 0) {
            $where = ['company_id' => $company_id];
        }
        $tariffs = Tariff::query()
            ->where([
                ['type', $type],
                ['service_type_id', $service_type_id],
            ])
            ->where($where)
            ->orderByDesc('open_time')
            ->first();
        if(!$tariffs)return_bobc('该城市未开通');
        $cost = self::calculatePredicts(time(), $total_time_int_m, $total_distance_km, $tariffs);
        $cost['total_time'] = $this->sToDhm($total_time_int_m);
        $cost['total_distance'] = $total_distance_km . 'km';
        $cost['steps'] = $path['steps'];
        return $cost;
    }

    /**
     * 代驾订单资费
     */
    public function dvingPredictByLoLass($origin, $destination, $type, $company_id)
    {
        $route = $this->getDriveRoute(['origin' => $origin, 'destination' => $destination]);

        $path = $route['paths'][0];
        $total_distance = $path['distance']; //总距离 m
        $total_distance_km = floor($total_distance / 1000 * 100) / 100; //总距离 km
        $total_time = $path['duration']; //总耗时
        $total_time_int_m = $total_time % 60 == 0 ? (int)$total_time : ((int)$total_time + 1); //总耗时 整分
        //获取资费信息
        $where = [];
        if ($company_id > 0) {
            $where = ['company_id' => $company_id];
        }
        $tariffs = DrivingTariff::query()
            ->where([
                ['type', $type],
            ])
            ->where($where)
            ->orderByDesc('open_time')
            ->first();
        if(!$tariffs)return_bobc('该城市未开通');
        $cost = self::for_driving_amoute(time(), $total_time_int_m, $total_distance_km, $tariffs);
        $cost['total_time'] = $this->sToDhm($total_time_int_m);
        $cost['total_distance'] = $total_distance_km . 'km';
        $cost['steps'] = $path['steps'];
        return $cost;
    }

    /**
     * 乘客实际费用计算
     */
    public function ActualCostOfPassengers(int $order_id)
    {
        $info = Orders::query()->with('order_distance')->where('id', $order_id)->first();
        return $this->getPredictByLoLas($info->order_distance->reality_start_coord, $info->order_distance->reality_end_coord, $info->order_distance->reality_start_time, $info->order_distance->reality_end_time, $info->service_type_id, $type = '1', $info->company_id, $order_id);
    }

    /**
     * 代驾乘客实际费用计算
     */
    public function drivingActualCostOfPassengers(int $order_id)
    {
        $info = Orders::query()->with('order_distance')->where('id', $order_id)->where('type', '1')->first();
        return $this->drivingGetPredictByLoLas($info->order_distance->reality_start_coord, $info->order_distance->reality_end_coord, $info->order_distance->reality_start_time, $info->order_distance->reality_end_time, $info->service_type_id, $type = '1', $info->company_id, $order_id,$info);
    }

    /**
     * @param $origin
     * @param $destination
     * @param $start_time
     * @param $end_time
     * @param $service_type_id
     * @param $type
     * @param $company_id
     * @param $order_id
     * @return array
     */
    public function drivingGetPredictByLoLas($origin, $destination, $start_time, $end_time, $service_type_id, $type, $company_id, $order_id,$order)
    {
        $minute = floor((strtotime($end_time) - strtotime($start_time)) % 86400 / 60) * 60;//计算实际上下车所用时间秒
        if ($minute <= 60) {
            $minute = 60;
        }
        return $this->drivingCostCalculation($origin, $destination, $start_time, $minute, $service_type_id, $type, $company_id, $order_id,$order);
    }

    /**
     * @param $origin
     * @param $destination
     * @param $start_time
     * @param $minute
     * @param $service_type_id
     * @param $type
     * @param $company_id
     * @param $order_id
     * @return mixed
     * @throws \App\Exceptions\BobException
     */
    public function drivingCostCalculation($origin, $destination, $start_time, $minute, $service_type_id, $type, $company_id, $order_id,$order)
    {
        $route = $this->getDriveRoute(['origin' => $origin, 'destination' => $destination]);
        $path = $route['paths'][0];
        $total_distance = $path['distance']; //总距离 m
        $total_distance_km = floor($total_distance / 1000 * 100) / 100; //总距离 km
        $total_time = $path['duration']; //总耗时
        $total_time_int_m = $total_time % 60 == 0 ? (int)$total_time : ((int)$total_time + 1); //总耗时 整分
        //获取资费信息
        $where = [];
        if ($company_id > 0) {
            $where = ['company_id' => $company_id];
        }
        $tariffs = DrivingTariff::query()
            ->where([
                ['type', $type],
                ['service_type_id', $service_type_id],
            ])
            ->where($where)
            ->orderByDesc('open_time')
            ->first();
        $cost = self::for_driving_amoute(strtotime($start_time), $total_time_int_m, $total_distance_km, $tariffs);
        $cost['minute'] = $minute / 60;   //总分钟
        $cost['total_distance'] = $total_distance_km; //总公里数
        $cost['total_time'] = $total_time_int_m; //分钟数
        $end_time = $order->order_distance->reality_start_time;
        $cost['waiting_timeout'] = self::waitingFee(floor((strtotime($end_time)-$order->arrive_time)/60), $tariffs->waiting_timeout); //超时等待费用
        $cost['total_distance_km'] = $total_distance_km; //超时等待费用
        return $cost;
    }


    /**
     * @param $origin  实际起点坐标
     * @param $destination 实际结束地点坐标
     * @param $boarding_time 开始时间
     * @param $boarding_time 结束时间
     * @param $service_type_id 业务类型ID
     * @param $type 类型
     * @param $company_id 公司ID
     */
    private function getPredictByLoLas($origin, $destination, $start_time, $end_time, $service_type_id, $type, $company_id, $order_id)
    {
        $minute = floor((strtotime($end_time) - strtotime($start_time)) % 86400 / 60) * 60;//计算实际上下车所用时间秒
        if ($minute <= 60) {
            $minute = 60;
        }
        return $this->CostCalculation($origin, $destination, $start_time, $minute, $service_type_id, $type, $company_id, $order_id);
    }

    /**
     * @param $origin
     * @param $destination
     * @param $start_time
     * @param $minute
     * @param $service_type_id
     * @param $type
     * 获取资费信息
     */
    private function CostCalculation($origin, $destination, $start_time, $minute, $service_type_id, $type, $company_id, $order_id)
    {

        $route = $this->getDriveRoute(['origin' => $origin, 'destination' => $destination]);

        $path = $route['paths'][0];
        $total_distance = $path['distance']; //总距离 m
        $total_distance_km = floor($total_distance / 1000 * 100) / 100; //总距离 km
        //获取资费信息
        $tariffs = Tariff::query()
            ->where(['service_type_id' => $service_type_id, 'type' => $type, 'company_id' => $company_id])
            ->orderByDesc('open_time')
            ->first();
        $cost = $this->calculatePredicts(strtotime($start_time), $minute, $total_distance_km, $tariffs);
        $cost['total_distance_km'] = $total_distance_km;
        $cost['minute'] = $minute / 60;
        $cost['waiting_timeout'] = self::waiting_timeout($order_id, $tariffs->waiting_timeout['data'], $tariffs->waiting_timeout['start_minute']);
        $cost['basics_subsidy'] = round($cost['basics_cost'] - $cost['total_mileage_cost'] - $cost['total_duration_cost'] - $cost['total_long_distance_cost'], 2);
        return $cost;
    }

    /**
     * 代驾费用计算
     */
    private function for_driving_amoute($start_time, $minute, $total_distance_km, object $tariffs)
    {
        $starting_price = $this->get_starting_priceCostByTime($start_time, $tariffs->starting_price);
        $default_minute_cost = $this->mileageCost($start_time, $tariffs->mileage);
        $predict = [
            'unpaid_cost' => 0, //需支付费用
            'starting_price' => 0, //起步价
            'total_cost' => 0, //总费用
            'total_mileage_cost' => 0, //总里程费用
            'total_duration_cost' => 0, //总时长费
            'mileage' => [], //里程费详情
            'duration' => [], //时长费详情
        ];
        $predict['starting_price'] = $starting_price['price'];
        if ($starting_price['km'] >= $total_distance_km) {
            $predict['mileage'][$starting_price['start_time']] = 0;
            $predict['unpaid_cost'] = $starting_price['price'];
            $predict['total_cost'] = $starting_price['price'];
        } else {
            $total_distance_km = floor(bcsub($total_distance_km, $starting_price['km'], 2));
            $predict['unpaid_cost'] = bcadd($starting_price['price'], bcmul($default_minute_cost['price'], $total_distance_km, 2), 2);
            $predict['mileage'][$starting_price['start_time']] = bcmul($default_minute_cost['price'], $total_distance_km, 2); //里程费
            $predict['total_cost'] = bcadd($starting_price['price'], bcmul($default_minute_cost['price'], $total_distance_km, 2), 2);
        }
        unset($starting_price['end_time'], $starting_price['start_time']);
        return $predict;
    }

    /**
     * @param $start_time
     * @param $minute
     * @param $total_distance_km
     * @param $tariffs 费用计算
     */
    private function calculatePredicts($start_time, $minute, $total_distance_km, $tariffs)
    {

        $default_minute_cost = []; //默认资费
        $default_minute_cost['mileage_cost'] = $tariffs->mileage[0]['price'];

        $default_minute_cost['duration_cost'] = $tariffs->duration['data'][0]['price'];
        $day_minute_arr = range(0, 1440 - 1);
        $default_minute_cost_arr = array_fill_keys($day_minute_arr, $default_minute_cost);// 默认费用

        $special_mileage_cost_arr = $this->getMinuteCost($tariffs->mileage, 'mileage_cost'); //特殊时段里程费用

        $special_duration_cost_arr = $this->getMinuteCost($tariffs->duration['data'], 'duration_cost'); //特殊时段时长费用

        $special_distance_km_cost_arr = $this->getLongDistanceKmCost($tariffs->distance, $total_distance_km); //特殊长途公里费用
        $basics_cost = 0;
        $starting_price = 0;
        if ($tariffs->rules == '0') {
            //滴滴模式基础费
            $basics_cost = $this->getBasicsCostByTime($start_time, $tariffs->basics);
        } else {
            //出租车计费获取起步价
            $starting_price = $this->get_starting_priceCostByTime($start_time, $tariffs->starting_price);
            $minute = $minute - $starting_price['min'] * 60;
            $total_distance_km = $total_distance_km - $starting_price['km'];
            if ($total_distance_km < 0) {
                $total_distance_km = 0;
            }
            if ($minute < 0) {
                $minute = 60;
            }
        }
        //相关时间
        $arrive_time = $start_time + $minute; //预计到达时间
        $boarding_Hi_arr = explode(':', date('H:i', $start_time));
        $arrive_Hi_arr = explode(':', date('H:i', $arrive_time));
        $boarding_minute = $boarding_Hi_arr[0] * 60 + $boarding_Hi_arr[1];
        $arrive_minute = $arrive_Hi_arr[0] * 60 + $arrive_Hi_arr[1];
        $total_minute = floor($minute / 60); //总分
        $mileage_minute = $total_distance_km / $total_minute; //每分钟公里

        //定义返回数据
        $predict = [
            'unpaid_cost' => 0, //需支付费用
            'basics_cost' => 0, //基础费用
            'starting_price' => 0, //起步价
            'total_cost' => 0, //总费用
            'total_mileage_cost' => 0, //总里程费用
            'total_duration_cost' => 0, //总时长费
            'total_long_distance_cost' => 0, //长途总费用
            'mileage' => [], //里程费详情
            'duration' => [], //时长费详情
            'long_distance' => [], //长途费详情
        ];

        //计算里程、时长费
        for ($minute = $boarding_minute; $minute <= $arrive_minute; $minute++) {

            $mileage_minute_cost = 0;
            $duration_minute_cost = 0;
            $mileage_key = '普通时段';
            $duration_key = '普通时段';

            //特殊时段里程费
            foreach ($special_mileage_cost_arr as $key => $mileage_minute_cost_arr) {
                if (isset($mileage_minute_cost_arr[$minute])) { //在特殊时段里程费

                    $mileage_minute_cost = $mileage_minute_cost_arr[$minute] * $mileage_minute;
                    $mileage_key = $key;

                }
            }
            //特殊时段时长费
            foreach ($special_duration_cost_arr as $key => $duration_minute_cost_arr) {
                if (isset($duration_minute_cost_arr[$minute])) { //在特殊时段里程费

                    $duration_minute_cost = $duration_minute_cost_arr[$minute];
                    $duration_key = $key;

                }
            }

            $mileage_minute_cost = $mileage_minute_cost === 0 ?
                $default_minute_cost_arr[$minute]['mileage_cost'] * $mileage_minute //普通时段里程费
                : $mileage_minute_cost;
            $duration_minute_cost = $duration_minute_cost === 0 ?
                $default_minute_cost_arr[$minute]['duration_cost'] //普通时段时长费
                : $duration_minute_cost;

            $predict['mileage'][$mileage_key] = isset($predict['mileage'][$mileage_key]) ?
                $predict['mileage'][$mileage_key] + $mileage_minute_cost //追加时段费用
                : $mileage_minute_cost;

            $predict['duration'][$duration_key] = isset($predict['duration'][$duration_key]) ?
                $predict['duration'][$duration_key] + $duration_minute_cost //追加时段费用
                : $duration_minute_cost;

        }
//        //计算长途费
        if ($special_distance_km_cost_arr) {

            $long_distance_start_km = key($special_distance_km_cost_arr);
            for ($km = $long_distance_start_km; $km <= ceil($total_distance_km); $km++) {

                $long_distance_cost = 0;
                $long_distance_key = 0;

                //长途费用
                foreach ($special_distance_km_cost_arr as $key => $distance_km_cost) {

                    //当前实际公里数
                    $real_km = $km > $total_distance_km ?
                        $total_distance_km - intval($total_distance_km)
                        : 0;

                    if ($km >= $key) { //在长途范围内

                        $long_distance_cost = $real_km ?
                            $long_distance_cost + $distance_km_cost * $real_km
                            : $long_distance_cost + $distance_km_cost;
                        $long_distance_key = $key - 1;

                    }

                }

                $long_distance_key = '超过' . $long_distance_key . '公里';
                $predict['long_distance'][$long_distance_key] = isset($predict['long_distance'][$long_distance_key]) ?
                    $predict['long_distance'][$long_distance_key] + $long_distance_cost
                    : $long_distance_cost;

            }
        }

        //格式化里程费、计算总里程费
        foreach ($predict['mileage'] as $key => $mileage_cost) {

            $mileage_cost = intval($mileage_cost * 100) / 100;
            $predict['mileage'][$key] = $mileage_cost;
            $predict['total_mileage_cost'] += $mileage_cost;

        }

        //格式化时长费、计算总时长费
        foreach ($predict['duration'] as $key => $duration_cost) {

            $duration_cost = intval($duration_cost * 100) / 100;
            $predict['duration'][$key] = $duration_cost;
            $predict['total_duration_cost'] += $duration_cost;

        }

//        //格式化长途费、计算总时长费
        foreach ($predict['long_distance'] as $key => $long_distance_cost) {

            $long_distance_cost = intval($long_distance_cost * 100) / 100;
            $predict['long_distance'][$key] = $long_distance_cost;
            $predict['total_long_distance_cost'] += $long_distance_cost;

        }
        $predict['basics_cost'] = $basics_cost ? $basics_cost : 0;     //基础费用
        $predict['starting_price'] = $starting_price ? $starting_price['price'] : 0; //起步价
        $predict['total_cost'] = intval(($predict['total_mileage_cost'] + $predict['total_duration_cost'] + $predict['total_long_distance_cost']) * 100) / 100;
        if ($tariffs->rules == '0') {
            $predict['unpaid_cost'] = intval(($predict['total_cost'] > $predict['basics_cost'] ? $predict['total_cost'] : $predict['basics_cost']) * 100) / 100;
        } else {
            if ($starting_price['km'] >= $total_distance_km && $starting_price['min'] >= $minute) $predict['unpaid_cost'] = $starting_price['price'];
            $predict['unpaid_cost'] = round($predict['total_cost'] + $starting_price['price'], 2);
        }
        return $predict;
    }

    /**
     * 根据时间获取当前 基础费用
     * @param int $time
     * @param array $rules
     */
    public function getBasicsCostByTime(int $time, array $rules)
    {

        $basics_cost = array_shift($rules)['price'];

        foreach ($rules as $key => $rule) {

            $start_time = strtotime($rule['start_time']);
            $end_time = $rule['end_time'] == '00:00' ?
                strtotime($rule['end_time']) + 86400 //接受时间是0点 加1天
                : strtotime($rule['end_time']);

            if ($time >= $start_time && $time < $end_time) {
                $basics_cost = $rule['price'];
                break;
            }
        }

        return $basics_cost;
    }

    /**
     * 根据时间获取里程费用
     */
    private function mileageCost(int $time, array $rules)
    {
        $mileageCost = array_shift($rules);

        foreach ($rules as $key => $rule) {
            $start_time = strtotime($rule['start_time']);
            $end_time = $rule['end_time'] == '00:00' ?
                strtotime($rule['end_time']) + 86400 //接受时间是0点 加1天
                : strtotime($rule['end_time']);
            if ($time >= $start_time && $time < $end_time) {
                $mileageCost = $rule;
                break;
            }
        }

        return $mileageCost;
    }

    /**
     * 根据时间获取当前起步费用
     * @param int $time
     * @param array $rules
     */
    public function get_starting_priceCostByTime(int $time, array $rules)
    {
        $starting_price = array_shift($rules);
        foreach ($rules as $key => $rule) {

            $start_time = strtotime($rule['start_time']);
            $end_time = $rule['end_time'] == '00:00' ?
                strtotime($rule['end_time']) + 86400 //接受时间是0点 加1天
                : strtotime($rule['end_time']);

            if ($time >= $start_time && $time < $end_time) {
                $starting_price = $rule;
                break;
            }
        }

        return $starting_price;
    }

    /**
     * 代驾等候费
     * 免费等候10分钟
     * 最长等待190分钟
     * 每分钟1元
     */
    protected function waitingFee(int $min, array $rules)
    {
        $rules = $rules['data'][0];
        if (!$rules) return 0;
        if ($rules['minutes'] < $min) {
            if ($rules['max_minute'] >= $min) {
                return $rules['price'] * ($min - $rules['minutes']);
            }
        }
        return 0;
    }

    /**
     * 获取每公里资费
     * @param array $rules
     * @param float $cur_distance_km
     * @return array
     */
    protected function getLongDistanceKmCost(array $rules, float $cur_distance_km)
    {
        $cur_distance_km = ceil($cur_distance_km);
        $km_cost_arr = [];

        foreach ($rules as $k => $rule) {
            if ($rule['start_dist'] >= $cur_distance_km)//当前里程小于最小长途费 直接返回空数组
                break;

            $km_cost_arr[$rule['start_dist'] + 1] = $rule['price'];

        }

        asort($km_cost_arr);

        return $km_cost_arr;
    }


    /**
     * 获取每分钟 费用
     * @param $rules
     * @return array
     */
    protected function getMinuteCost(array $rules)
    {
        $minute_cost_arr = [];

        foreach ($rules as $k => $rule) {

            if ($rule['start_time'] == '普通时段') //第一条为默认价格
                continue;

            $rule['end_time'] = $rule['end_time'] == '00:00' ? '24:00' : $rule['end_time'];
            $row_start_arr = explode(':', $rule['start_time']); //22:00
            $row_end_arr = explode(':', $rule['end_time']); //24:00]
            $row_start_minute = $row_start_arr[0] * 60 + $row_start_arr[1];
            $row_end_minute = $row_end_arr[0] * 60 + $row_end_arr[1];
            $row_end_minute -= 1; //规则结束时间减1
            $row_minute_arr = range($row_start_minute, $row_end_minute);
            $cost_key = $rule['start_time'] . '-' . $rule['end_time'];
            $minute_cost_arr[$cost_key] = array_fill_keys($row_minute_arr, $rule['price']);

        }

        return $minute_cost_arr;
    }

    /**
     * 秒转化为具体时间 天小时分
     * @param int $time 时间戳
     */
    protected function sToDhm(int $time)
    {

        $dhm = 0;
        $d = floor($time / (3600 * 24));
        $h = floor(($time % (3600 * 24)) / 3600);
        $m = floor((($time % (3600 * 24)) % 3600) / 60);
        if ($d > '0') {
            $dhm = $d . '天' . $h . '小时' . $m . '分';
        } else {
            if ($h != '0') {
                $dhm = $h . '小时' . $m . '分';
            } else {
                $dhm = $m . '分';
            }
        }

        return $dhm;
    }
}